﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.CompilerServices;
using Kaidou.Util;
using Kaidou.Persister;
using System.Collections;
using Kaidou.Model;
using System.Resources;

namespace Kaidou.Bll
{
    /**zhou-anyuan
     * 受注したシールの受付処理.
     * シール受付明細(trn_juchu_uketuke) に保持した情報を元に trn_purch_seal へシール枚数分のレコードを挿入する。
     * cron により夜間バッチの別プロセスとして起動する。
     * シール番号は TRN_ReceiptOrderManager1 で採番済み。
     *
     * @author Sakai
     */
    public class TRN_ReceiptOrderManager2
    {
        private static ResourceManager m_ResourceManager;
        /** Singleton Instance */
        private static TRN_ReceiptOrderManager2 instance = new TRN_ReceiptOrderManager2();
        /** 排他処理のためのフラグ */
        private static bool locked = false;

        /** デフォルトコンストラクタ */
        private TRN_ReceiptOrderManager2()
        {
        }

        /**
         * 処理の開始時に Instance を取得し、ロックする
         *
         * @return このクラスの Singleton Instance. 他で使用中のときは null を返す
         */
        public static TRN_ReceiptOrderManager2 checkout(ResourceManager resourceManager)
        {
            if (locked)
            {
                return null;
            }
            locked = true;
            m_ResourceManager = resourceManager;
            return instance;
        }

        /**
         * 処理終了後にロックを解除する
         */
        public static void checkin()
        {
            locked = false;
        }

        /**
         * 注文受付処理の実行.
         * 排他処理のため、locked フラグを持つ.
         * ロックのオン・オフのため、checkout(), checkin() を実行する
         */
        [MethodImpl(MethodImplOptions.Synchronized)]
        public void exec()
        {
            if (!locked)
            {
                LogManager.info("TRN_ReceiptOrderManager2 - Class \"TRN_ReceiptOrderManager2\" is not locked. Process is canceled.");
                throw new Exception("Class \"TRN_ReceiptOrderManager2\" is not locked. Process is canceled.");
            }

            try
            {
                //Connection con = Pool.getConnection();
                SqlDB con = new SqlDB();
                try
                {
                    //ConnectionUtility.setAutoCommit(con, false);

                    //①排他ロックをかける
                    //②trn_juchu_uketuke.uketuke_sts='10' に該当する受注Dレコードを取得
                    TRN_Juchu_UketukePersister perU = new TRN_Juchu_UketukePersister();
                    TRN_Purch_SealPersister perS = new TRN_Purch_SealPersister();
                    List<TrnJuchud> targetList = perU.findReceiptOrderTarget(con);
                    if (targetList == null || targetList.Count == 0)
                    {
                        targetList = new List<TrnJuchud>();
                        LogManager.info("TRN_ReceiptOrderManager2 - #############################################");
                        LogManager.info("TRN_ReceiptOrderManager2 - # There is no order detail for prosess now. #");
                        LogManager.info("TRN_ReceiptOrderManager2 - #############################################");
                    }
                    con.TransBegin();
                    try
                    {
                        for (int i = 0; i < targetList.Count(); i++)
                        {
                            try
                            {
                                TrnJuchud targetD = targetList[i];
                                String tranInfo = "(Order No.=" + targetD.Id.JuchuNo + "/Detail No.=" + targetD.Id.JuchuRecNo + "/Quantity=" + targetD.SealQty + ")";

                                System.DateTime startDate = System.DateTime.Now;
                                //③begin transaction
                                LogManager.info("TRN_ReceiptOrderManager2 - #############################################");
                                LogManager.info("TRN_ReceiptOrderManager2 - Begin transaction for 1 order detail!! " + tranInfo + " --------------------------");




                                //④シール購入管理明細にレコードを insert
                                String strStartNo = targetD.SealStrNo;
                                String strEndNo = targetD.SealEndNo;
                                int startNo = int.Parse(strStartNo.Substring(2));
                                int endNo = int.Parse(strEndNo.Substring(2));
                                perS.insertByProcedure(con, targetD, startNo, endNo);

                                System.DateTime endDate = System.DateTime.Now;
                                //⑤update trn_juchu_uketuke set uketuke_sts='90', start_date=startDate, end_date=now
                                perU.update(con, targetD, startDate, endDate);

                                //⑥commit()

                                LogManager.info("TRN_ReceiptOrderManager2 - Commited transaction!! " + tranInfo + " --------------------------");
                                LogManager.info("TRN_ReceiptOrderManager2 - #############################################");
                            }
                            catch(Exception ie)
                            {
                                LogManager.error("TRN_ReceiptOrderManager2 - insertLoopError!" + ie.ToString());
                            }
                        }
                        con.TransCommit();
                    }
                    catch (Exception e)
                    {
                        //⑦rollback()
                        con.TransRollback();

                        LogManager.info("TRN_ReceiptOrderManager2 - #############################################");
                        LogManager.info("TRN_ReceiptOrderManager2 - Rollbacked transaction!! ");// + tranInfo + " --------------------------"
                        LogManager.debug("TRN_ReceiptOrderManager2 - " + e.ToString());

                        LogManager.debug("TRN_ReceiptOrderManager2 - " + e.StackTrace);

                        LogManager.info("TRN_ReceiptOrderManager2 - #############################################");
                    }

                    //受付から90日以上経過した受付レコードを削除
                    try
                    {

                        int keepTerm = int.Parse(TRN_ReceiptOrderManager2.m_ResourceManager.GetString("uketuke_keep_term").ToString());

                        LogManager.debug("TRN_ReceiptOrderManager2 - uketuke.keep.term = " + keepTerm + "days");
                        perU.deleteBeforeBorder(con, keepTerm);
                    }
                    catch (Exception e)
                    {
                        LogManager.debug("TRN_ReceiptOrderManager2 - ####################################################");
                        LogManager.debug("TRN_ReceiptOrderManager2 - # Couldn't get keep term value from property file. #");
                        LogManager.debug("TRN_ReceiptOrderManager2 - ####################################################");
                    }
                    //①の排他ロックを解除
                }
                finally
                {
                    con.Close();
                    //ConnectionUtility.setAutoCommit(con, true);
                    //Pool.releaseConnection(con);
                }
            }
            catch (Exception e)
            {
                throw e;
            }

        }

        /*
         * 確認シール番号をシーケンスから取得
         *
         * @param con
         * @param total_seal_qty シール枚数
         * @return シール番号を保持したモデル
         * @throws FrameworkException
        private static NextSealNoSequenceModel getSealNo(Connection con, int total_seal_qty) throws FrameworkException {
            Logger.logWrite(TRN_ReceiptOrderManager2.class.getName(), "D", "getSealNo in");

            NextSealNoSequenceModel seq_model = new NextSealNoSequenceModel();
            NextSealNoSequencePersister seq_per = new NextSealNoSequencePersister();
            InputErrorException ie = new InputErrorException();

            try {
                Logger.logWrite(TRN_ReceiptOrderManager2.class.getName(), "D", "NextvalProcedure call start");
                seq_model = seq_per.NextvalProcedure(con, total_seal_qty);

                Logger.logWrite(TRN_ReceiptOrderManager2.class.getName(), "D", "NextvalProcedure call end");

                Logger.logWrite(TRN_ReceiptOrderManager2.class.getName(), "D", "getSealNo out");
            } catch (PersisterSQLException pe) {
                Logger.logWrite(TRN_ReceiptOrderManager2.class.getName(), "E", "getSealNo", pe.getSQLException());
                throw pe;
            } finally {
                try {
                    Pool.releaseConnection(con);
                } catch (Exception e) {
                    Logger.logWrite(TRN_ReceiptOrderManager2.class.getName(), "F", "getSealNo - finally", e);
                }
            }

            if (ie.getErrorCount() != 0) {
                throw ie;
            }
            return seq_model;
        }
         */

        /*
         * 確認シール注文の受付処理の採番を rollback する.
         * ストアドプロシージャは rollback 不能
         *
         * @param con
         * @param startNo
         * @throws FrameworkException
        private static void rollbackStartEndSealNo(Connection con, int startNo) throws FrameworkException {
            if (startNo == 0) {
                return;
            }

            NextSealNoSequencePersister seq_per = new NextSealNoSequencePersister();
            try {
                seq_per.rollback(con, startNo);
            } catch (PersisterSQLException e) {
                throw new FrameworkException(e);
            }
        }
         */

    }
}
